package cn.lanqiao.system.interceptor;

import cn.lanqiao.system.util.Result;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 方法执行顺序为 preHandle – Controller 方法 – postHandle – afterCompletion
 * preHandle: 访问controller之前调用
 * postHandle: ModelAndView渲染前调用
 * afterCompletion: 完成请求和响应后调用
 * ps:需要配置config
 * */
@Component
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 在yaml配置文件中读取秘钥
     * */
    @Value("${cn.lanqiao.key}")
    private String key;

    /**
     * 使用拦截器实现JWT登录验证
     * */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {
            //获得token操作
            String token = request.getHeader("Authorization");
            if(token == null){
               return failResult(401,"请先登录！！",response);
            }
            //解密操作
            Algorithm algorithm = Algorithm.HMAC256(key);//设置加密方式
            JWTVerifier jwtVerifier = JWT.require(algorithm).build();//创建认证对象，创建失败会抛出AlgorithmMismatchException异常。
            DecodedJWT decodedJWT = jwtVerifier.verify(token.substring(7));//对去掉头信息的token进行验证
            return true;
        } catch (JWTDecodeException e){
            return failResult(402,"秘钥格式错误！",response);
        } catch (SignatureVerificationException e){
            return failResult(403,"秘钥解密错误！",response);
        } catch (TokenExpiredException e) {
            return failResult(405,"token过期，请重新登录！",response);
        } catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 验证失败统一向前端返回错误结果
     * @param code 错误码
     * @param message 错误信息
     * @param response 响应对象
     * */
    public boolean failResult(int code ,String message, HttpServletResponse response){
        try {
            ObjectMapper objectMapper = new ObjectMapper();//使用jackson，也可以使用fastjson
            response.setContentType("text/html;charset=UTF-8");
            response.setStatus(code);
            response.getWriter().print( objectMapper.writeValueAsString(Result.error(code,message)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }
}
